local SkillDefine	 = require("skill.Define")
local Util			 = require("common.Util")
local Obj			 = require("core.Obj")
local ScanConditions = require("skill.ScanConditions")	-- 敌友关系区别扫描
-- *************  AOE扫描 **************

local roundCollision 	= Util.roundCollision
local distUtil		 	= Util.dist
local rectCollision	 	= Util.rectCollision
local getAngle		 	= Util.getAngle
local fanCollision	 	= Util.fanCollision
local pi			 	= math.acos(-1)
local ACTTACK_TYPE_SELF	= SkillDefine.ACTTACK_TYPE_SELF

local AOE_TYPE_SINGLE	= 1		-- 单体
	  AOE_TYPE_ROUND	= 2		-- 椭圆
local AOE_TYPE_MAP		= 5		-- 全地图
local AOE_TYPE_NONE		= 6		-- 无范围（比如放置Obj）


local MAX_AOE_COUNT		= 30	-- 最大AOE扫描上限
data = data or {}

function handle(aoeType, obj, target, unit, callback, conditionFunc, maxCount, arg1, arg2)

	if not callback then return end
		
	-- 特殊AOE类型
	if aoeType		== AOE_TYPE_SINGLE then 
		local dist = arg1 -- 挥空距离
		single(obj, target, unit, callback, conditionFunc, dist)
		return
	elseif aoeType	== AOE_TYPE_MAP then
		map(obj, unit, callback, conditionFunc, maxCount)
		return
	elseif aoeType	== AOE_TYPE_NONE then
		callback(obj, target, unit)
		return
	end
	
	
	-- 其他AOE类型
	local condition				= unit.utilityConfig.friendAndFoeConditions	-- 敌友关系
	local scanConditionsHandle	= ScanConditions[condition]					-- 敌友关系区别扫描函数
	local aoeCondition			= aoes[aoeType]								-- AOE碰撞检测函数
	data.conditionFunc		 	= conditionFunc
	data[1]				 		= arg1
	data[2]						= arg2
	
	assert(aoeCondition, aoeType)

	if not maxCount or maxCount>MAX_AOE_COUNT or maxCount<1 then
		maxCount = MAX_AOE_COUNT
	end
	
	scanConditionsHandle(obj, callback, aoeCondition, maxCount, unit)		-- 开始扫描
	
end

function utilityScan(aoeType, obj, target, unit, callback, conditionFunc, maxCount, arg1, arg2)
	local oldArg1 = data[1]
	local oldArg2 = data[2]
	
	handle(aoeType, obj, target, unit, callback, conditionFunc, maxCount, arg1, arg2)
	
	data[1]		  = oldArg1
	data[2]		  = oldArg2
end

-- 单体
function single(obj, target, unit, callback, conditionFunc, dist)
	if unit.utilityConfig.acttackCenter == ACTTACK_TYPE_SELF then	--自身
		target = obj
	end
	if not target then return end	-- 目标不存在

	-- 是否是锁定目标
	local isLocked = not dist or dist==0 or distUtil(target.x, target.y, unit.tx, unit.ty) <= dist + Obj.getRadius(target)
	if isLocked and conditionFunc(obj, target, unit) then
		callback(obj, target, unit)
	end
end

-- 椭圆碰撞检测
function round(obj, target, unit)
	local radius = data[1]
	local isHit  = roundCollision(unit.tx, unit.ty, radius, target.x, target.y, Obj.getRadius(target))
	return isHit and data.conditionFunc(obj, target, unit)
end

--矩形(八方向)
function rect(obj, target, unit)
	local conditionFunc = data.conditionFunc
	local rectWidth		= data[1]
	local rectHeight	= data[2]
	local rectX			= unit.x	
	local rectY			= unit.y - rectHeight/2
	local rectCenterX	= rectX
	local rectCenterY	= unit.y
	local angle			= (unit.dir - 2) * -45
	
	local isHit			= rectCollision(angle, rectCenterX, rectCenterY, rectX, rectY, rectWidth, rectHeight, target.x, target.y, Obj.getRadius(target))
	return isHit and conditionFunc(obj, target, unit)
end

-- 矩形(自由角度)
function rectAuto(obj, target, unit)
	local conditionFunc = data.conditionFunc
	local rectWidth		= data[1]
	local rectHeight	= data[2]
	assert(rectHeight,"unit.utilityID: "..unit.utilityID.." unit.skillID: "..unit.skillID)

	local rectX			= unit.x	
	local rectY			= unit.y - rectHeight/2
	local rectCenterX	= rectX
	local rectCenterY	= unit.y
	local angle			= getAngle(unit.x,unit.y,unit.tx,unit.ty)
	local isHit			= rectCollision(angle, rectCenterX, rectCenterY, rectX, rectY, rectWidth, rectHeight, target.x, target.y, Obj.getRadius(target))
	return isHit and conditionFunc(obj, target, unit)
end

-- 自身朝向矩形
function rectDir(obj, target, unit)
	local conditionFunc = data.conditionFunc
	local rectWidth		= data[1]
	local rectHeight	= data[2]	
	local rectX			= unit.x - rectWidth/2
	local rectY			= unit.y - rectHeight/2
	local rectCenterX	= unit.x
	local rectCenterY	= unit.y
	local angle			= unit.dir * -45
	local isHit			= rectCollision(angle, rectCenterX, rectCenterY, rectX, rectY, rectWidth, rectHeight, target.x, target.y, Obj.getRadius(target))
	
	return isHit and conditionFunc(obj, target, unit)
end

-- 矩形（自由角度）并且自动算出距离目标的 距离
function rectAutoWidth(obj, target, unit)
	local conditionFunc = data.conditionFunc
	local rectWidth		= distUtil(unit.x, unit.y, unit.tx, unit.ty)
	local rectHeight	= data[1]	
	local rectX			= unit.x
	local rectY			= unit.y - rectHeight/2
	local rectCenterX	= rectX
	local rectCenterY	= unit.y
	local angle			= getAngle(unit.x, unit.y, unit.tx, unit.ty)
	local isHit			= rectCollision(angle, rectCenterX, rectCenterY, rectX, rectY, rectWidth, rectHeight, target.x, target.y, Obj.getRadius(target))
	
	return isHit and conditionFunc(obj, target, unit)
end

function rectDouble(obj, target, unit)
  local conditionFunc = data.conditionFunc
  local rectWidth   = data[1]
  local rectHeight  = data[2]
  local rectX     = unit.x  
  local rectY     = unit.y - rectHeight/2
  local rectCenterX = rectX
  local rectCenterY = unit.y
  local angle     = getAngle(unit.x,unit.y,unit.tx,unit.ty)
  
  local isHit     = rectCollision(angle, rectCenterX, rectCenterY, rectX, rectY, rectWidth, rectHeight, target.x, target.y, Obj.getRadius(target))
  
  if not isHit then
     angle = angle + 180
     isHit     = rectCollision(angle, rectCenterX, rectCenterY, rectX, rectY, rectWidth, rectHeight, target.x, target.y, Obj.getRadius(target))
  end
  return isHit and conditionFunc(obj, target, unit)
end


-- 扇形
function fan(obj, target, unit)
	local conditionFunc = data.conditionFunc
	local aoeRadius		= data[1]
	local angle			= pi / ( 180 / data[2] * 2 )
	local isHit			= fanCollision(unit.x, unit.y, unit.dir, target.x,target.y, Obj.getRadius(target), aoeRadius, angle)
	return isHit and conditionFunc(obj, target, unit)
end

-- 全地图
function map(obj, unit, callback, conditionFunc, maxCount)
	local scene = Obj.scenes[unit.sceneID]
	if not scene then return end
	
	local count = 0
	
	for k = 1, scene[0] do
		local target = scene[k]
		if conditionFunc(obj, target, unit) then
			callback(obj, target, unit)
			if maxCount then 
				count = count + 1
				if count>= maxCount then
					return	
				end
			end
		end
	end
end


-- AOE配置
aoes = { 
	nil,		--单体 不扫描
	round,		--圈
	rect,		--矩形(8方向)
	fan,		--扇形
	map,		--全地图
	none,		--无范围
	rectAuto,	--矩形（自由角度）
	rectDir,	--自身朝向矩形
	rectAutoWidth,	--矩形（自由角度）并且自动算出距离目标的 距离
	rectDouble, --矩形，双方向（八卦，符文)
}
